package com.foreverwin.mes.so.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.foreverwin.mes.common.constants.Constants;
import com.foreverwin.mes.common.constants.HandleBOConstants;
import com.foreverwin.mes.common.enums.HandleEnum;
import com.foreverwin.mes.core.base.FrontPage;
import com.foreverwin.mes.core.exception.BusinessException;
import com.foreverwin.mes.core.utils.CommonMethods;
import com.foreverwin.mes.core.utils.DateUtil;
import com.foreverwin.mes.core.utils.StringUtils;
import com.foreverwin.mes.meapi.dto.GenerateNextNumberRequest;
import com.foreverwin.mes.meapi.dto.GenerateNextNumberResponse;
import com.foreverwin.mes.meapi.enums.CustomFieldsConstant;
import com.foreverwin.mes.meapi.model.*;
import com.foreverwin.mes.meapi.service.*;
import com.foreverwin.mes.production.service.WorkCenterShiftService;
import com.foreverwin.mes.so.dto.ShopOrderDispatchVO;
import com.foreverwin.mes.so.mapper.ShopOrderDispatchMapper;
import com.foreverwin.mes.so.model.ShopOrderDispatch;
import com.foreverwin.mes.so.model.ShopOrderDispatchDetail;
import com.foreverwin.mes.so.service.CycleTimeConfigService;
import com.foreverwin.mes.so.service.ShopOrderDispatchDetailService;
import com.foreverwin.mes.so.service.ShopOrderDispatchService;
import com.google.common.collect.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 工单派工主表 服务实现类
 * </p>
 *
 * @author Syngna
 * @since 2020-02-06
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ShopOrderDispatchServiceImpl extends ServiceImpl<ShopOrderDispatchMapper, ShopOrderDispatch> implements ShopOrderDispatchService {


    @Autowired
    private ShopOrderDispatchMapper shopOrderDispatchMapper;

    @Autowired
    private ShopOrderDispatchDetailService shopOrderDispatchDetailService;

    @Autowired
    private ResrceService resrceService;

    @Autowired
    private OperationService operationService;

    @Autowired
    private CustomFieldsService customFieldsService;

    @Autowired
    private CycleTimeConfigService cycleTimeConfigService;

    @Autowired
    WorkCenterShiftService workCenterShiftService;

    @Autowired
    NextNumberService nextNumberService;

    @Autowired
    ShopOrderService shopOrderService;

    @Autowired
    BomService bomService;

    @Override
    public Page<ShopOrderDispatch> selectPage(FrontPage<ShopOrderDispatch> frontPage, ShopOrderDispatch shopOrderDispatch) {
        EntityWrapper<ShopOrderDispatch> queryWrapper = new EntityWrapper<>();
        queryWrapper.setEntity(shopOrderDispatch);
        return super.selectPage(frontPage.getPagePlus(), queryWrapper);
    }

    @Override
    public List<ShopOrderDispatch> selectList(ShopOrderDispatch shopOrderDispatch) {
        EntityWrapper<ShopOrderDispatch> queryWrapper = new EntityWrapper<>();
        queryWrapper.setEntity(shopOrderDispatch);
        return super.selectList(queryWrapper);
    }

    @Override
    public Page<ShopOrderDispatch> selectDispatchShopOrderPage(Page page, ShopOrderDispatch shopOrderDispatch) {
        Locale locale = LocaleContextHolder.getLocale();
        String site = shopOrderDispatch.getSite();
        String shopOrder = shopOrderDispatch.getShopOrder();
        String item = shopOrderDispatch.getItem();
        String itemDescription = shopOrderDispatch.getItemDescription();
        String globalQuery = shopOrderDispatch.getGlobalQuery();
        page.setRecords(shopOrderDispatchMapper.selectDispatchShopOrderList(page, locale.getLanguage(), site, shopOrder, item, itemDescription, globalQuery));
        return page;
    }

    @Override
    public ShopOrderDispatch getDispatchShopOrder(ShopOrderDispatch shopOrderDispatch) {
        Locale locale = LocaleContextHolder.getLocale();
        String site = shopOrderDispatch.getSite();
        String shopOrder = shopOrderDispatch.getShopOrder();
        List<ShopOrderDispatch> shopOrderDispatcheList = shopOrderDispatchMapper.selectDispatchShopOrderList(locale.getLanguage(), site, shopOrder, null, null, null);
        return shopOrderDispatcheList != null && shopOrderDispatcheList.size() > 0 ? shopOrderDispatcheList.get(0) : null;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Resrce getResourceDispatchInfo(String site, String resrce, String itemBo) {
        if (StringUtils.isBlank(resrce)) {
            throw BusinessException.build("设备编号不能为空");
        }
        String resourceBo = StringUtils.genHandle(HandleBOConstants.RESOURCE_BO, site, resrce);
        String item = StringUtils.trimHandle(itemBo);
        Resrce result = resrceService.selectByCode(CommonMethods.getSite(), resrce);
        if (result == null) {
            throw BusinessException.build("设备【" + resrce + "】不存在");
        }
        String handle = result.getHandle();
        // 设备批量
        String resourceBatchQty = "";
        // 任务量原则
        String splitPrinciple = "";
        List<CustomFields> customFieldsList = customFieldsService.listByHandle(handle);
        for (CustomFields customFields : customFieldsList) {
            switch (customFields.getAttribute()) {
                case CustomFieldsConstant.KW_RESOURCE_BATCH_QTY:
                    resourceBatchQty = customFields.getValue();
                    break;
                case CustomFieldsConstant.KW_RESOURCE_SPLIT_PRINCIPLE:
                    splitPrinciple = customFields.getValue();
                    break;
                default:
                    break;
            }
        }
        if (StringUtils.isBlank(splitPrinciple)) {
            throw BusinessException.build("设备【" + resrce + "】任务量原则未设定");
        }
        result.setSplitPrinciple(splitPrinciple);
        result.setResrceBatch(resourceBatchQty);

        BigDecimal cycleTime = cycleTimeConfigService.getCycleTime(site, resourceBo, itemBo);
        if ("2".equals(splitPrinciple) && cycleTime == null) {
            throw BusinessException.build("设备【" + resrce + "】任务量原则为按班次，对应物料【" + item + "】未设定CT时间");
        } else if ("3".equals(splitPrinciple) && StringUtils.isBlank(resourceBatchQty)) {
            throw BusinessException.build("设备【" + resrce + "】任务量原则为按批次/锅次，未设定批次/锅次大小");
        }
        // CT时间
        result.setCycleTime(cycleTime == null ? "" : cycleTime.toString());
        // 理论产能
        if (cycleTime != null) {
            Map<String, Object> workCenterShift = workCenterShiftService.getCurrentShiftOfResource(site, resrce, new Date());
            if (workCenterShift == null) {
                throw BusinessException.build("设备【" + resrce + "】对应的班次信息维护不完整");
            }
            Date beginTime = (Date) workCenterShift.get("beginTime");
            Date endTime = (Date) workCenterShift.get("endTime");
            BigDecimal theoryCapacity = new BigDecimal(endTime.getTime()).subtract(new BigDecimal(beginTime.getTime())).divide(new BigDecimal("1000")).divide(cycleTime, BigDecimal.ROUND_HALF_UP);
            result.setTheoryCapacity(theoryCapacity.toString());
        }
        return result;
    }

    /**
     * 检查设备是否空闲
     *
     * @param site
     * @param shopOrderDispatch
     */
    @Override
    public void isResourceFree(String site, ShopOrderDispatch shopOrderDispatch) {
        String resource = shopOrderDispatch.getResrce();
        Date plannedStartDate = shopOrderDispatch.getDispStartDate();
        Date plannedCompDate = shopOrderDispatch.getDispCompDate();
        Optional<ShopOrderDispatch> optionalShopOrderDispatch = selectList(new EntityWrapper<ShopOrderDispatch>()
                .eq(ShopOrderDispatch.SITE, site)
                .eq(ShopOrderDispatch.RESRCE, resource)
                .gt(ShopOrderDispatch.DISP_COMP_DATE, plannedStartDate)
                .lt(ShopOrderDispatch.DISP_START_DATE, plannedCompDate)
                .orderAsc(Lists.newArrayList(ShopOrderDispatch.DISP_START_DATE)))
                .stream()
                .findFirst();
        if (optionalShopOrderDispatch.isPresent()) {
            ShopOrderDispatch shopOrderDispatchDo = optionalShopOrderDispatch.get();
            String startDate = DateUtil.format(shopOrderDispatchDo.getDispStartDate(), DateUtil.DATE_FORMAT3);
            String compDate = DateUtil.format(shopOrderDispatchDo.getDispCompDate(), DateUtil.DATE_FORMAT3);
            throw BusinessException.build("工单【" + shopOrderDispatchDo.getShopOrder() + "】于【" + startDate + "】~【" + compDate + "】已在设备【" + resource + "】预派任务【" + shopOrderDispatchDo.getDispTaskNo() + "】");
        }
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public ShopOrderDispatch splitSimple(String site, ShopOrderDispatch shopOrderDispatch) {
        List<ShopOrderDispatchDetail> shopOrderDispatchDetailList = new ArrayList<>();
        ShopOrderDispatchDetail shopOrderDispatchDetail = new ShopOrderDispatchDetail();
        shopOrderDispatchDetail.setScheduleQty(shopOrderDispatch.getDispQty());
        shopOrderDispatchDetail.setPlannedStartDate(shopOrderDispatch.getDispStartDate());
        shopOrderDispatchDetail.setPlannedCompDate(shopOrderDispatch.getDispCompDate());
        shopOrderDispatchDetail.setStatus(ShopOrderDispatchDetail.STATUS_RELEASABLE);
        shopOrderDispatchDetail.setCreator(shopOrderDispatch.getCreator());
        shopOrderDispatchDetail.setUpdater(shopOrderDispatch.getCreator());

        shopOrderDispatchDetailList.add(shopOrderDispatchDetail);
        shopOrderDispatch.setShopOrderDispatchDetailList(shopOrderDispatchDetailList);
        return shopOrderDispatch;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public ShopOrderDispatch splitByShift(String site, ShopOrderDispatch shopOrderDispatch) {
        String resrce = shopOrderDispatch.getResrce();
        String theoryCapacity = shopOrderDispatch.getTheoryCapacity();
        BigDecimal dispQty = shopOrderDispatch.getDispQty();
        Date dispStartDate = shopOrderDispatch.getDispStartDate();
        BigDecimal cycleTime = shopOrderDispatch.getCycleTime();
        // 计算派工完成日期
        Long endTimeMills = new BigDecimal(dispStartDate.getTime()).add(cycleTime.multiply(dispQty).multiply(new BigDecimal("1000"))).longValue();
        Date dispCompDate = new Date(endTimeMills);
        shopOrderDispatch.setDispCompDate(dispCompDate);
        // 计算首批数量及时间
        Map<String, Object> workCenterShift = workCenterShiftService.getCurrentShiftOfResource(site, resrce, dispStartDate);
        Date beginTime = (Date) workCenterShift.get("beginTime");
        Date endTime = (Date) workCenterShift.get("endTime");
        Long shiftPeriord = endTime.getTime() - beginTime.getTime();
        // 按班次和CT时间拆分任务
        int count = 1;
        BigDecimal firstBatchQty = new BigDecimal(endTime.getTime()).subtract(new BigDecimal(dispStartDate.getTime())).divide(new BigDecimal("1000")).divide(cycleTime, BigDecimal.ROUND_HALF_UP);
        BigDecimal remainQty = dispQty.subtract(firstBatchQty);

        List<ShopOrderDispatchDetail> shopOrderDispatchDetailList = new ArrayList<>();
        ShopOrderDispatchDetail shopOrderDispatchDetail = new ShopOrderDispatchDetail();
        shopOrderDispatchDetail.setScheduleQty(firstBatchQty.min(dispQty));
        shopOrderDispatchDetail.setPlannedStartDate(dispStartDate);
        shopOrderDispatchDetail.setPlannedCompDate(endTime);
        shopOrderDispatchDetail.setStatus(ShopOrderDispatchDetail.STATUS_RELEASABLE);
        shopOrderDispatchDetail.setCreator(shopOrderDispatch.getCreator());
        shopOrderDispatchDetail.setUpdater(shopOrderDispatch.getCreator());
        shopOrderDispatchDetailList.add(shopOrderDispatchDetail);
        if (remainQty.compareTo(BigDecimal.ZERO) > 0) {
            Date lastShiftCompleteDate = endTime;
            BigDecimal[] temp = remainQty.divideAndRemainder(new BigDecimal(theoryCapacity));
            if (temp[0].compareTo(BigDecimal.ZERO) > 0) {
                for (int i = 0; i < temp[0].intValue(); i++) {
                    ShopOrderDispatchDetail shopOrderDispatchDetailCopy = new ShopOrderDispatchDetail();
                    BeanUtils.copyProperties(shopOrderDispatchDetail, shopOrderDispatchDetailCopy);
                    shopOrderDispatchDetailCopy.setScheduleQty(new BigDecimal(theoryCapacity));
                    shopOrderDispatchDetailCopy.setPlannedStartDate(new Date(endTime.getTime() + shiftPeriord * i));
                    lastShiftCompleteDate = new Date(endTime.getTime() + shiftPeriord * (i + 1));
                    shopOrderDispatchDetailCopy.setPlannedCompDate(lastShiftCompleteDate);
                    shopOrderDispatchDetailList.add(shopOrderDispatchDetailCopy);
                }
            }
            if (temp[1].compareTo(BigDecimal.ZERO) > 0) {
                ShopOrderDispatchDetail shopOrderDispatchDetailEnd = new ShopOrderDispatchDetail();
                BeanUtils.copyProperties(shopOrderDispatchDetail, shopOrderDispatchDetailEnd);
                shopOrderDispatchDetailEnd.setScheduleQty(temp[1]);
                shopOrderDispatchDetailEnd.setPlannedStartDate(lastShiftCompleteDate);
                shopOrderDispatchDetailEnd.setPlannedCompDate(dispCompDate);
                shopOrderDispatchDetailList.add(shopOrderDispatchDetailEnd);
            }
        }
        shopOrderDispatch.setShopOrderDispatchDetailList(shopOrderDispatchDetailList);
        return shopOrderDispatch;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public ShopOrderDispatch splitByResourceBatch(String site, ShopOrderDispatch shopOrderDispatch) {
        String resrce = shopOrderDispatch.getResrce();
        BigDecimal resrceBatch = shopOrderDispatch.getResrceBatch();
        BigDecimal dispQty = shopOrderDispatch.getDispQty();
        if (resrceBatch == null || resrceBatch.compareTo(BigDecimal.ZERO) <= 0) {
            throw BusinessException.build("设备【" + resrce + "】对应的设备批量值【" + resrceBatch + "】设定错误");
        }
        List<ShopOrderDispatchDetail> shopOrderDispatchDetailList = new ArrayList<>();
        ShopOrderDispatchDetail shopOrderDispatchDetail = new ShopOrderDispatchDetail();
        shopOrderDispatchDetail.setPlannedStartDate(shopOrderDispatch.getDispStartDate());
        shopOrderDispatchDetail.setPlannedCompDate(shopOrderDispatch.getDispCompDate());
        shopOrderDispatchDetail.setStatus(ShopOrderDispatchDetail.STATUS_RELEASABLE);
        shopOrderDispatchDetail.setCreator(shopOrderDispatch.getCreator());
        shopOrderDispatchDetail.setUpdater(shopOrderDispatch.getCreator());

        BigDecimal[] temp = dispQty.divideAndRemainder(resrceBatch);
        if (temp[0].compareTo(BigDecimal.ZERO) > 0) {
            for (int i = 0; i < temp[0].intValue(); i++) {
                ShopOrderDispatchDetail shopOrderDispatchDetailCopy = new ShopOrderDispatchDetail();
                BeanUtils.copyProperties(shopOrderDispatchDetail, shopOrderDispatchDetailCopy);
                shopOrderDispatchDetailCopy.setScheduleQty(resrceBatch);
                shopOrderDispatchDetailList.add(shopOrderDispatchDetailCopy);
            }
        }
        if (temp[1].compareTo(BigDecimal.ZERO) > 0) {
            shopOrderDispatchDetail.setScheduleQty(temp[1]);
            shopOrderDispatchDetailList.add(shopOrderDispatchDetail);
        }
        shopOrderDispatch.setShopOrderDispatchDetailList(shopOrderDispatchDetailList);
        return shopOrderDispatch;
    }

    @Override
    public void saveBatch(String site, String user, ShopOrderDispatchVO shopOrderDispatchVO) {
        List<String> dispatchDeleteHandleList = shopOrderDispatchVO.getDispatchDeleteHandleList();
        List<String> dispatchDetailDeleteHandleList = shopOrderDispatchVO.getDispatchDetailDeleteHandleList();
        List<ShopOrderDispatch> shopOrderDispatcheList = shopOrderDispatchVO.getShopOrderDispatchList();
        Date now = new Date();
        if (shopOrderDispatcheList != null && shopOrderDispatcheList.size() > 0) {
            String shopOrder = shopOrderDispatcheList.get(0).getShopOrder();
            Integer maxSeq = getMaxDispNo(site, shopOrder);

            List<ShopOrderDispatch> updateMasterList = new ArrayList<>();
            List<ShopOrderDispatch> insertMasterList = new ArrayList<>();
            List<ShopOrderDispatchDetail> updateDetailList = new ArrayList<>();
            List<ShopOrderDispatchDetail> insertDetailList = new ArrayList<>();
            for (ShopOrderDispatch shopOrderDispatch : shopOrderDispatcheList) {
                shopOrderDispatch.setSite(site);
                if (StringUtils.notBlank(shopOrderDispatch.getHandle())) {
                    shopOrderDispatch.setUpdater(user);
                    shopOrderDispatch.setModifiedDateTime(now);
                    if (shopOrderDispatch.getDispDate() == null && shopOrderDispatch.getShopOrderDispatchDetailList() != null && shopOrderDispatch.getShopOrderDispatchDetailList().size() > 0) {
                        shopOrderDispatch.setDispDate(now);
                    }
                    updateMasterList.add(shopOrderDispatch);
                } else {
                    shopOrderDispatch.setCreator(user);
                    shopOrderDispatch.setUpdater(user);
                    if (shopOrderDispatch.getShopOrderDispatchDetailList() != null && shopOrderDispatch.getShopOrderDispatchDetailList().size() > 0) {
                        shopOrderDispatch.setDispDate(now);
                    }
                    shopOrderDispatch.setCreatedDateTime(now);
                    shopOrderDispatch.setModifiedDateTime(now);
                    insertMasterList.add(shopOrderDispatch);
                }
            }
            if (insertMasterList.size() > 0) {
                for (ShopOrderDispatch shopOrderDispatch : insertMasterList) {
                    // 生成任务号
                    List<Operation> operationList = operationService.listByResource(StringUtils.genHandle(HandleBOConstants.RESOURCE_BO, site, shopOrderDispatch.getResrce()));
                    if (operationList.size() == 0) {
                        throw BusinessException.build("设备【" + shopOrderDispatch.getResrce() + "】没有找到对应的操作");
                    }
                    String workshopSection = operationList.get(0).getOperation();
                    if (workshopSection.length() > 2) {
                        workshopSection = workshopSection.substring(0, 2);
                    }
                    shopOrderDispatch.setWorkShopSection(workshopSection);

                    String shopOrderDispatchBo = "";
                    maxSeq++;
                    String taskNo = shopOrder + "-" + StringUtils.leftPad(maxSeq + "", "0", 2);
                    shopOrderDispatch.setDispTaskNo(taskNo);
                    shopOrderDispatchBo = StringUtils.genHandle(HandleBOConstants.SHOP_ORDER_DISPATCH_BO, site, taskNo);
                    shopOrderDispatch.setHandle(shopOrderDispatchBo);
                    List<ShopOrderDispatchDetail> shopOrderDispatchDetailList = shopOrderDispatch.getShopOrderDispatchDetailList();
                    if (shopOrderDispatchDetailList != null && shopOrderDispatchDetailList.size() > 0) {
                        String nextNumberType = "SHOP_ORDER_DISPATCH_TASK_NO_" + operationList.get(0).getOperation();
                        GenerateNextNumberRequest generateNextNumberRequest = new GenerateNextNumberRequest();
                        generateNextNumberRequest.setNextNumberType(nextNumberType);
                        Map<String, Object> customData = new HashMap<>();
                        customData.put("WC", workshopSection);
                        generateNextNumberRequest.setCustomData(customData);
                        generateNextNumberRequest.setNumberOfValues(shopOrderDispatchDetailList.size());
                        generateNextNumberRequest.setSite(site);

                        // 按工序设定编号规则，没有则自动创建
                        String nextNumberHandle = StringUtils.genHandle(HandleBOConstants.NEXT_NUBMER_BO, site, nextNumberType);
                        NextNumber nextNumber = nextNumberService.selectByIdForUpdate(nextNumberHandle);
                        if (nextNumber == null) {
                            nextNumber = new NextNumber();
                            nextNumber.setHandle(nextNumberHandle);
                            nextNumber.setSite(site);
                            nextNumber.setNextNumberType(nextNumberType);
                            nextNumber.setPrefix("%WC%%DATE_TIME.[yyMMdd]%");
                            nextNumber.setSequenceBase("10");
                            nextNumber.setSequenceLength("4");
                            nextNumber.setCurrentSequence("1");
                            nextNumber.setIncr("1");
                            nextNumber.setReset("D");
                            nextNumber.setCreatedDateTime(new Date());
                            nextNumber.setModifiedDateTime(new Date());
                            nextNumberService.insert(nextNumber);
                        }

                        GenerateNextNumberResponse generateNextNumberResponse = nextNumberService.generateNextValues(generateNextNumberRequest);
                        List<String> ids = generateNextNumberResponse.getIds();
                        for (int i = 0; i < shopOrderDispatchDetailList.size(); i++) {
                            int index = i + 1;
                            ShopOrderDispatchDetail shopOrderDispatchDetail = shopOrderDispatchDetailList.get(i);
                            String childTaskNo = ids.get(i);
                            shopOrderDispatchDetail.setHandle(StringUtils.genHandle(HandleBOConstants.SHOP_ORDER_DISPATCH_DETAIL_BO, site, shopOrderDispatchDetail.getShopOrder(), childTaskNo));
                            shopOrderDispatchDetail.setSite(site);
                            shopOrderDispatchDetail.setShopOrderDispatchBo(shopOrderDispatchBo);
                            shopOrderDispatchDetail.setDispTaskNo(taskNo);
                            shopOrderDispatchDetail.setDispTaskChildNo(childTaskNo);
                            shopOrderDispatchDetail.setRecipeStatus(ShopOrderDispatchDetail.STATUS_RELEASABLE);
                            shopOrderDispatchDetail.setSeq(index);
                            shopOrderDispatchDetail.setDispDate(now);
                            shopOrderDispatchDetail.setCreator(user);
                            shopOrderDispatchDetail.setUpdater(user);
                            shopOrderDispatchDetail.setCreatedDateTime(now);
                            shopOrderDispatchDetail.setModifiedDateTime(now);
                            insertDetailList.add(shopOrderDispatchDetail);
                        }
                    }
                }
                this.insertBatch(insertMasterList);
            }
            if (updateMasterList.size() > 0) {
                for (ShopOrderDispatch shopOrderDispatch : updateMasterList) {
                    int totalNewChildQty = 0;
                    List<ShopOrderDispatchDetail> shopOrderDispatchDetailList = shopOrderDispatch.getShopOrderDispatchDetailList();
                    if (shopOrderDispatchDetailList != null && shopOrderDispatchDetailList.size() > 0) {
                        for (ShopOrderDispatchDetail shopOrderDispatchDetail : shopOrderDispatchDetailList) {
                            if (StringUtils.isBlank(shopOrderDispatchDetail.getHandle())) {
                                totalNewChildQty++;
                            }
                        }
                        GenerateNextNumberRequest generateNextNumberRequest = new GenerateNextNumberRequest();
                        generateNextNumberRequest.setNextNumberType("SHOP_ORDER_DISPATCH_TASK_NO");
                        Map<String, Object> customData = new HashMap<>();
                        customData.put("WC", shopOrderDispatch.getWorkShopSection());
                        generateNextNumberRequest.setCustomData(customData);
                        generateNextNumberRequest.setNumberOfValues(totalNewChildQty);
                        generateNextNumberRequest.setSite(site);
                        GenerateNextNumberResponse generateNextNumberResponse = nextNumberService.generateNextValues(generateNextNumberRequest);
                        List<String> ids = generateNextNumberResponse.getIds();
                        int index = 0;
                        for (ShopOrderDispatchDetail shopOrderDispatchDetail : shopOrderDispatchDetailList) {
                            if (StringUtils.notBlank(shopOrderDispatchDetail.getHandle())) {
                                shopOrderDispatchDetail.setDispDate(now);
                                shopOrderDispatchDetail.setUpdater(user);
                                shopOrderDispatchDetail.setModifiedDateTime(now);
                                updateDetailList.add(shopOrderDispatchDetail);
                            } else {
                                String childTaskNo = ids.get(index);
                                index++;
                                shopOrderDispatchDetail.setHandle(StringUtils.genHandle(HandleBOConstants.SHOP_ORDER_DISPATCH_DETAIL_BO, site, shopOrderDispatchDetail.getShopOrder(), childTaskNo));
                                shopOrderDispatchDetail.setSite(site);
                                shopOrderDispatchDetail.setShopOrderDispatchBo(shopOrderDispatch.getHandle());
                                shopOrderDispatchDetail.setDispTaskNo(shopOrderDispatch.getDispTaskNo());
                                shopOrderDispatchDetail.setDispTaskChildNo(childTaskNo);
                                shopOrderDispatchDetail.setRecipeStatus(ShopOrderDispatchDetail.STATUS_RELEASABLE);
                                shopOrderDispatchDetail.setSeq(index);
                                shopOrderDispatchDetail.setDispDate(now);
                                shopOrderDispatchDetail.setCreator(user);
                                shopOrderDispatchDetail.setUpdater(user);
                                shopOrderDispatchDetail.setCreatedDateTime(now);
                                shopOrderDispatchDetail.setModifiedDateTime(now);
                                insertDetailList.add(shopOrderDispatchDetail);
                            }
                        }
                    }
                }
                this.updateBatchById(updateMasterList);
            }
            if (insertDetailList.size() > 0) {
                shopOrderDispatchDetailService.insertBatch(insertDetailList);
            }
            if (updateDetailList.size() > 0) {
                shopOrderDispatchDetailService.updateBatchById(updateDetailList);
            }
        }
        if (dispatchDeleteHandleList != null && dispatchDeleteHandleList.size() > 0) {
            this.deleteBatchIds(dispatchDeleteHandleList);
            shopOrderDispatchDetailService.delete(new EntityWrapper<ShopOrderDispatchDetail>().in(ShopOrderDispatchDetail.SHOP_ORDER_DISPATCH_BO, dispatchDeleteHandleList));
        }
        if (dispatchDetailDeleteHandleList != null && dispatchDetailDeleteHandleList.size() > 0) {
            shopOrderDispatchDetailService.deleteBatchIds(dispatchDetailDeleteHandleList);
        }
    }

    /**
     * 根据工单获取数据
     *
     * @param site
     * @param shopOrder
     * @return
     */
    @Override
    public List<ShopOrderDispatch> listByShopOrder(String site, String shopOrder) {
        return shopOrderDispatchMapper.selectByShopOrder(site, shopOrder);
    }

    private List<ShopOrderDispatchDetail> getMaxDispDetailGroupNo(List<ShopOrderDispatch> shopOrderDispatcheList) {
        List<String> handleList = shopOrderDispatcheList.stream().map(ShopOrderDispatch::getHandle).collect(Collectors.toList());
        return shopOrderDispatchMapper.selectMaxDispDetailGroupNo(handleList);
    }

    private Integer getMaxDispNo(String site, String shopOrder) {
        List<ShopOrderDispatch> shopOrderDispatchList = this.listByShopOrder(site, shopOrder);
        int seq = 0;
        for (ShopOrderDispatch shopOrderDispatch : shopOrderDispatchList) {
            String dispatchTaskNo = shopOrderDispatch.getDispTaskNo();
            Integer temp = Integer.parseInt(dispatchTaskNo.substring(dispatchTaskNo.length() - 2));
            if (temp > seq) {
                seq = temp;
            }
        }
        return seq;
    }

    @Override
    public List<Resrce> listResourceByShopOrder(String site, String shopOrder) {
        String shopOrderBo = HandleEnum.SHOP_ORDER.getHandle(site, shopOrder);
        String bomBo = shopOrderService.getBomBo(shopOrderBo);
        if (bomBo != null) {
            Bom bomDo = bomService.getBomInfo(site, bomBo);
            if (bomDo != null) {
                bomBo = bomDo.getHandle();
                String cupRoad = null;
                CustomFields customFields = customFieldsService.getAttributeValue(bomBo, Constants.ALTERNATIVE_BOM_ID);
                if (customFields != null) {
                    cupRoad = customFields.getValue();
                }
                if (cupRoad != null && Constants.CUP_ROADS.contains(cupRoad)) {
                    List<String> resourceHandles = customFieldsService.selectList(new EntityWrapper<CustomFields>()
                            .eq(CustomFields.ATTRIBUTE, Constants.CUP_ROAD)
                            .eq(CustomFields.VALUE, cupRoad))
                            .stream()
                            .map(CustomFields::getHandle)
                            .filter(handle -> handle.startsWith(HandleEnum.RESOURCE.getPrefix()))
                            .filter(handle -> HandleEnum.RESOURCE.getPart(handle, 0).equals(site))
                            .collect(Collectors.toList());
                    return resourceHandles.isEmpty() ? Lists.newArrayList() : resrceService.selectList(new EntityWrapper<Resrce>()
                            .in(Resrce.HANDLE, resourceHandles));
                }
            }
        }
        return resrceService.selectList(new EntityWrapper<Resrce>().eq(Resrce.SITE, site));
    }

}